/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SDRV_VIC_H_
#define SDRV_VIC_H_

#include "Vic_Irq_Cfg.h"

#if !defined(VIC_SOFT_IRQ_CLR_BY_HANDLER)
#define VIC_SOFT_IRQ_CLR_BY_HANDLER 0
#endif

#define DEFAULT_IRQ_PRIORITY    10U

#define irq_lld_initialize  sdrv_vic_lld_init
#define irq_lld_set_priority    sdrv_vic_lld_set_priority
#define irq_lld_disable sdrv_vic_lld_int_disable
#define irq_lld_enable  sdrv_vic_lld_int_enable
#define irq_lld_mask(x)    sdrv_vic_lld_mask_low_priority(x, TRUE)
#define irq_lld_get_priority    sdrv_vic_lld_get_priority
#define irq_lld_get_current_priority    sdrv_vic_lld_current_running_priority
#define irq_lld_unmask  sdrv_vic_lld_unmask_all_priority
#define irq_lld_acknowledge sdrv_vic_lld_ack

#if defined(CONFIG_VIC_IRQ_INTERRUPT_MODE)
#define irq_lld_complete(irq)
#else
#define irq_lld_complete(irq)   sdrv_vic_lld_eoi(irq)
#endif

/* Not supported interface by VIC. */
#define irq_lld_set_trigger_mode(irq, mode) (void)mode

#if !defined(ASSEMBLY)

#include <Compiler.h>
#include "atomic.h"
/**
 * Type 0: v1.0
 * Type 1: v1.1 vectored irq mode
 * Type 2: v1.1 non-vectored irq mode
 */
#define NO_INT_NEST_ERRATA      0
#define INT_NEST_ERRATA_TYPE_0  1
#define INT_NEST_ERRATA_TYPE_1  2
#define INT_NEST_ERRATA_TYPE_2  3

#define BIT_SET(x, bit) (((x) & (1UL << (bit))) ? 1 : 0)
#define BITMAP_BITS_PER_WORD (sizeof(unsigned long) * 8)
#define BITMAP_NUM_WORDS(x) (((x) + BITMAP_BITS_PER_WORD - 1) / BITMAP_BITS_PER_WORD)
#define BITMAP_WORD(x) ((x) / BITMAP_BITS_PER_WORD)
#define BITMAP_BIT_IN_WORD(x) ((x) & (BITMAP_BITS_PER_WORD - 1))

#define BITMAP_BITS_PER_INT (sizeof(unsigned int) * 8)
#define BITMAP_BIT_IN_INT(x) ((x) & (BITMAP_BITS_PER_INT - 1))
#define BITMAP_INT(x) ((x) / BITMAP_BITS_PER_INT)

static inline int bitmap_set(unsigned long *bitmap, int bit)
{
    unsigned long mask = 1UL << BITMAP_BIT_IN_INT(bit);
    return arch_atomic_or(&((int *)bitmap)[BITMAP_INT(bit)], mask) & mask ? 1 : 0;
}

static inline int bitmap_clear(unsigned long *bitmap, int bit)
{
    unsigned long mask = 1UL << BITMAP_BIT_IN_INT(bit);

    return arch_atomic_and(&((int *)bitmap)[BITMAP_INT(bit)], ~mask) & mask ? 1:0;
}

static inline int bitmap_test(unsigned long *bitmap, int bit)
{
    return BIT_SET(bitmap[BITMAP_WORD(bit)], BITMAP_BIT_IN_WORD(bit));
}

#include "Mcu_Soc.h"

uint32 sdrv_vic_lld_mask_low_priority(uint32 pri_threshold, boolean user);

void sdrv_vic_lld_unmask_all_priority(void);

void sdrv_vic_lld_init(uint32 base, uint32 intr_num, int (*isr)(uint32));
void sdrv_vic_lld_set_priority(uint32 vector,
                               uint32 pri);
void sdrv_vic_lld_int_enable(uint32 vector);
void sdrv_vic_lld_int_disable(uint32 vector);
uint32 sdrv_vic_lld_get_priority(uint32 vector);
uint32 sdrv_vic_lld_current_running_priority(void);
void sdrv_vic_lld_set_fiq_req_src(uint32 vector);
uint32 sdrv_vic_lld_get_active_fiq_src(void);
uint32 sdrv_vic_lld_ack(void);
#if !defined(CONFIG_VIC_IRQ_INTERRUPT_MODE)
void sdrv_vic_lld_eoi(uint32 vector);
#endif
void sdrv_vic_lld_trigger_soft_int(uint32 vector);
void sdrv_vic_lld_clear_soft_int(uint32 vector);
#if (VIC_SOFT_IRQ_CLR_BY_HANDLER == 1)
boolean sdrv_vic_lld_is_soft_int(uint32  vector);
#endif
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))

#if (CONFIG_VIC_CORE_NUM > 1)
static inline int get_core_id(void)
{
    return Mcu_GetCoreID();
}
#else
#define get_core_id()      0
#endif
#endif // !ASSEMBLY

#endif // !SDRV_VIC_H_
